import React, { Fragment } from 'react';
import { Alert, Table } from 'antd';
import PropTypes from 'prop-types';
import { formatMessage, FormattedMessage } from 'umi/locale';
import { Resizable } from 'react-resizable';
import 'react-resizable/css/styles.css';
import './indexResizeable.css';
import styles from './index.less';

const getValue = obj =>
  Object.keys(obj)
    .map(key => obj[key])
    .join(',');

const ResizeableTitle = props => {
  const { onResize, width, ...restProps } = props;

  if (!width) {
    return <th {...restProps} />;
  }

  return (
    <Resizable width={width} height={0} onResize={onResize}>
      <th {...restProps} />
    </Resizable>
  );
};

/**
 * 自己封装的简化表格操作的ETable
 *
 * 如果 ETable 要同时多选多页的数据，请 处理一下 数据，数据增加一个 字段：key, key 不重复就可以了
 */
export default class ETable extends React.Component {
  static propTypes = {
    selectedRows: PropTypes.array,
    selectedIds: PropTypes.array,
    selectedIndexs: PropTypes.array,
    onSelectRow: PropTypes.func,
    onSelectRowKeys: PropTypes.array,
    primaryKey: PropTypes.string,
    onChange: PropTypes.func,
    allowMultiPageSelects: PropTypes.bool,
    resizeEnable: PropTypes.bool,
  };

  static defaultProps = {
    selectedRows: [], //选中的行的数据,数组，可能是多行; [...record] 数据
    selectedIds: [], //选中行的ids; [...record.id] 数据主键
    selectedIndexs: [], //官方名称：selectedRowKeys; row.index 行的下标集合；[...index]； 调用方如果修改该取值，就可以动态控制表格的选中项
    onSelectRow: () => {}, //选中行的ids
    onSelectRowKeys: ['selectedIndexs', 'selectedRows', 'selectedIds'], //默认值
    primaryKey: 'id', //数据对象的主键，默认是id,不是id请进行修改
    onChange: () => {}, //表格 过滤、排序事件处理，表格 Table 本来也有这个方法
    allowMultiPageSelects: false, //是否允许多页选中，如果允许，组件内部默认对数据 dataSource 增加 key 属性
    resizeEnable: false, //是否开启头部可以左右拖动的功能
  };

  constructor(props) {
    super(props);
    //使用resize功能才有这个state
    this.state = {
      columns: this.props.columns,
    };
  }

  cleanSelectedKeys = () => {
    this.props.selectedIndexs.splice(0, this.props.selectedIndexs.length);
    const { selectedIndexs } = this.props;

    this.executionOnSelectRow(selectedIndexs, [], []);
  };

  handleRowSelectChange = (selectedIndexs, selectedRows) => {
    const selectedIds = selectedRows.map(obj => obj[this.props.primaryKey]);
    this.executionOnSelectRow(selectedIndexs, selectedRows, selectedIds);
  };

  executionOnSelectRow = (selectedIndexs, selectedRows, selectedIds) => {
    const key1 = this.props.onSelectRowKeys[0];
    const key2 = this.props.onSelectRowKeys[1];
    const key3 = this.props.onSelectRowKeys[2];

    const aObj = { [key1]: selectedIndexs };
    const cObj = { [key2]: selectedRows };
    const dObj = { [key3]: selectedIds };
    this.props.onSelectRow(aObj, cObj, dObj);
  };

  /**
   * 排序、翻页、过滤发生变化的时候回调
   * @param pagination
   * @param filtersArg
   * @param sorter
   */
  handleTableChange = (pagination, filtersArg, sorter) => {
    const { onChange } = this.props;
    if (onChange) {
      //分页1：onChange 页码改变的回调，参数是改变后的页码及每页条数
      //分页2：onShowSizeChange pageSize 变化的回调
      //排除 上面之外的筛选或者排序的时候在进行回调
      if (filtersArg && sorter.order) {
        //这里仅保留 排序和过滤 进行回调

        const filters = Object.keys(filtersArg).reduce((obj, key) => {
          const newObj = { ...obj };
          newObj[key] = getValue(filtersArg[key]);
          return newObj;
        }, {});
        const params = {
          //page: pagination.current,//currentPage
          //limit: pagination.pageSize,//pageSize
          //...param,
          ...filters,
        };
        if (sorter.field) {
          params.sidx = sorter.columnKey;
          //table colume直接用 `key`有问题，这里重新换回去
          if (params.sidx === 'keyAlias') {
            params.sidx = 'key';
          }
          params.order = sorter.order === 'ascend' ? 'asc' : 'desc';
        }
        onChange(params);
      }
    }
  };

  /**
   * 排序、翻页、过滤发生变化的时候回调,  这里仅保留 排序和过滤回调
   */
  filtersSorterChange = (pagination, filtersArg, sorter) => {
    const { page, limit, ...param } = this.params;

    const filters = Object.keys(filtersArg).reduce((obj, key) => {
      const newObj = { ...obj };
      newObj[key] = getValue(filtersArg[key]);
      return newObj;
    }, {});

    const params = {
      page: pagination.current, //currentPage
      limit: pagination.pageSize, //pageSize
      ...param,
      ...filters,
    };
    if (sorter.field) {
      params.sidx = sorter.columnKey;
      if (params.sidx === 'keyAlias') {
        params.sidx = 'key';
      }
      params.order = sorter.order === 'ascend' ? 'asc' : 'desc';
    }
    this.params = params;
    this.requestList();
  };

  onRowClick = (record, index) => {
    const { type } = this.props;
    if (type === 'radio') {
      const selectedIndexs = [index];
      const selectedRows = [record];
      this.executionOnSelectRow(selectedIndexs, selectedRows);
    } else {
      let { selectedRows } = this.props;
      let { selectedIds } = this.props;
      if (selectedIds) {
        const i = selectedIds.indexOf(record[this.props.primaryKey]);
        if (i === -1) {
          selectedIds.push(record[this.props.primaryKey]);
          this.props.selectedIndexs.push(index);
          selectedRows.push(record);
        } else {
          selectedIds.splice(i, 1);
          this.props.selectedIndexs.splice(i, 1);
          selectedRows.splice(i, 1);
        }
      } else {
        selectedIds = [record[this.props.primaryKey]];
        this.props.selectedIndexs.splice(0, this.props.selectedIndexs.length);
        this.props.selectedIndexs.push(index);
        selectedRows = [record];
      }
      this.executionOnSelectRow(this.props.selectedIndexs, selectedRows, selectedIds);
    }
  };

  handleResize = index => (e, { size }) => {
    this.setState(({ columns }) => {
      const nextColumns = [...columns];
      nextColumns[index] = {
        ...nextColumns[index],
        width: size.width,
      };
      return { columns: nextColumns };
    });
  };

  tableInit = () => {
    const {
      selectedRows,
      selectedIds,
      selectedIndexs, //官方名称：selectedRowKeys
      allowMultiPageSelects, //自己添加
      type = 'checkbox', //checkbox or radio,默认checkbox
      size = 'small',
      dataSource,
      resizeEnable,
      ...rest
    } = this.props;

    if (allowMultiPageSelects && dataSource !== null && dataSource !== undefined) {
      //处理数据 增加字段key
      for (let i = 0; i < dataSource.length; i += 1) {
        dataSource[i].key = i;
      }
    }

    //resize相关
    const columns = this.state.columns;
    const componentsResize = resizeEnable
      ? {
          header: {
            cell: ResizeableTitle,
          },
        }
      : null;
    const columnsResize = columns.map((col, index) => ({
      ...col,
      onHeaderCell: column => ({
        width: column.width,
        onResize: this.handleResize(index),
      }),
    }));

    //https://ant.design/components/table-cn/#rowSelection
    const rowSelection =
      this.props.rowSelection === undefined
        ? {
            type, //多选/单选，checkbox or radio ,默认checkbox
            selectedRowKeys: selectedIndexs, //指定选中项的 key 数组，需要和 onChange 进行配合
            onChange: this.handleRowSelectChange,
            getCheckboxProps: record => ({
              disabled: record.disabled,
            }),
          }
        : null;

    return (
      <Table
        bordered
        size={size}
        {...rest}
        rowSelection={rowSelection}
        dataSource={dataSource}
        onChange={this.handleTableChange}
        onRow={(record, index) => ({
          onDoubleClick: () => {
            this.onRowClick(record, index);
          },
        })}
        //下面resize相关
        columns={resizeEnable ? columnsResize : columns}
        {...(resizeEnable ? { components: componentsResize } : {})}
      />
    );
  };

  tableAlert = () => {
    const { selectedIndexs, rowSelection } = this.props;
    return rowSelection === undefined ? (
      <div className={styles.tableAlert}>
        <Alert
          message={
            <Fragment>
              <FormattedMessage
                id="ours.curd.list.base-form.have-select-text"
                defaultMessage="已选择"
              />{' '}
              <a style={{ fontWeight: 600 }}>{selectedIndexs.length}</a>{' '}
              <FormattedMessage
                id="ours.curd.list.base-form.have-select-unit"
                defaultMessage="项"
              />
              &nbsp;&nbsp;
              <a onClick={this.cleanSelectedKeys} style={{ marginLeft: 24 }}>
                <FormattedMessage
                  id="ours.curd.list.base-form.have-select-clear"
                  defaultMessage="清空"
                />
              </a>
            </Fragment>
          }
          type="info"
          showIcon
        />
      </div>
    ) : (
      <div className={styles.tableAlert} />
    );
  };

  render() {
    return (
      <div className={styles.standardTable}>
        {this.tableAlert()}
        {this.tableInit()}
      </div>
    );
  }
}
